/*
 * BingoView.java
 */
package bingo;

import java.awt.Color;
import java.net.*;
import java.io.*;
import java.util.LinkedList;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;

/**
 * The application's main frame.
 */
public class BingoView extends FrameView {

    public BingoView(SingleFrameApplication app) {
        super(app);

        initComponents();

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
            }
        });


        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {

            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                } else if ("message".equals(propertyName)) {
                    String text = (String) (evt.getNewValue());
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer) (evt.getNewValue());
                }
            }
        });
    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = BingoApp.getApplication().getMainFrame();
            aboutBox = new BingoAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        BingoApp.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jTextField1 = new javax.swing.JTextField();
        jButton2 = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jTextField2 = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jTextField3 = new javax.swing.JTextField();
        jPanel1 = new javax.swing.JPanel();
        jButton3 = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        jList2 = new javax.swing.JList();
        jButton4 = new javax.swing.JButton();
        menuBar = new javax.swing.JMenuBar();

        mainPanel.setMaximumSize(new java.awt.Dimension(1592, 566));
        mainPanel.setName("mainPanel"); // NOI18N
        mainPanel.setPreferredSize(new java.awt.Dimension(1592, 566));

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(bingo.BingoApp.class).getContext().getActionMap(BingoView.class, this);
        jButton1.setAction(actionMap.get("quit")); // NOI18N
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(bingo.BingoApp.class).getContext().getResourceMap(BingoView.class);
        jButton1.setText(resourceMap.getString("jButton1.text")); // NOI18N
        jButton1.setName("jButton1"); // NOI18N

        jTextField1.setText(resourceMap.getString("jTextField1.text")); // NOI18N
        jTextField1.setName("jTextField1"); // NOI18N

        jButton2.setAction(actionMap.get("connect")); // NOI18N
        jButton2.setText(resourceMap.getString("jButton2.text")); // NOI18N
        jButton2.setName("jButton2"); // NOI18N

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        jList1.setEnabled(false);
        jList1.setName("jList1"); // NOI18N
        jScrollPane1.setViewportView(jList1);

        jTextField2.setText(resourceMap.getString("jTextField2.text")); // NOI18N
        jTextField2.setName("jTextField2"); // NOI18N

        jLabel1.setFont(resourceMap.getFont("jLabel1.font")); // NOI18N
        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
        jLabel1.setName("jLabel1"); // NOI18N

        jTextField3.setText(resourceMap.getString("jTextField3.text")); // NOI18N
        jTextField3.setName("jTextField3"); // NOI18N

        jPanel1.setName("jPanel1"); // NOI18N

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 599, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 396, Short.MAX_VALUE)
        );

        jButton3.setAction(actionMap.get("start")); // NOI18N
        jButton3.setText(resourceMap.getString("jButton3.text")); // NOI18N
        jButton3.setName("jButton3"); // NOI18N

        jScrollPane2.setName("jScrollPane2"); // NOI18N

        jList2.setName("jList2"); // NOI18N
        jScrollPane2.setViewportView(jList2);

        jButton4.setText(resourceMap.getString("jButton4.text")); // NOI18N
        jButton4.setName("jButton4"); // NOI18N

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 132, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(jButton4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 132, Short.MAX_VALUE))
                        .addContainerGap(608, Short.MAX_VALUE))
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGap(10, 10, 10)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addGroup(mainPanelLayout.createSequentialGroup()
                                .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 210, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jButton3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                            .addGroup(mainPanelLayout.createSequentialGroup()
                                .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 214, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 180, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 650, Short.MAX_VALUE)
                        .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 381, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(42, 42, 42))))
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 395, Short.MAX_VALUE)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 395, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jButton1)
                            .addComponent(jButton4))))
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGap(6, 6, 6)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jButton3)
                            .addComponent(jButton2)))
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGap(18, 18, 18)
                        .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 102, Short.MAX_VALUE)))
                .addContainerGap())
        );

        menuBar.setName("menuBar"); // NOI18N

        setComponent(mainPanel);
        setMenuBar(menuBar);
    }// </editor-fold>//GEN-END:initComponents

    @Action
    /*
     * legt fest, ob einem Spiel bei getreten oder eines erstellt wird (läd dann auch Datei, textfeld3),
     * stellt Verbindung her zur IP im textfeld1 schickt Name(textfeld2)
     */
    public void connect() {
        try {
            a = new Socket(jTextField1.getText(), 1238);
            if (sendName()) {
                setRole();
                sendFile();
                String[][] arrayField = getFields();
                buttonserstellen(arrayField);
                this.jTextField1.disable();
                this.jTextField2.disable();
                this.jTextField3.disable();
                jButton3.setEnabled(true);
                jButton2.setEnabled(false);
            }
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

/**
 * erstellt Spielfeld, weisst den Knoepfen Worte zu (erzeugt Spielkarten-GUI)
 */
    private void buttonserstellen(String[][] dataField) {
        this.buttons = new JButton[5][5];
        for (int i = 0; i < buttons.length; i++) {
            for (int j = 0; j < buttons[i].length; j++) {
                this.buttons[i][j]=new JButton();
                this.buttons[i][j].setBounds((i ) * 113, (j ) * 73, 110, 72);
                this.buttons[i][j].setText(dataField[i][j]);
                this.jPanel1.add(this.buttons[i][j]);
                this.buttons[i][j].setVisible(true);
                this.buttons[i][j].setFocusable(false);
                final String a = new String(dataField[i][j]);
                final JButton dummyBtn = this.buttons[i][j];
                final JLabel dummyLab = this.jLabel1;
                dummyBtn.addActionListener(new ActionListener() {
                    
                    public void actionPerformed(ActionEvent event) {
                        dummyBtn.getText();
                        if (text.contains(a)) {
                            dummyBtn.setForeground(Color.red);
                            dummyBtn.setBackground(Color.red);
                            if(wincheck())
                            {
                                win = true;
                                dummyLab.setText("BINGO!");
                            }
                            //dummyBtn.setText("KLICK!");
                        }
                    }
                });
            }
        }
        this.jPanel1.setVisible(false);
        this.jPanel1.setVisible(true);
    }

    /*
     * prueft, ob Spieler gewonnen hat (5 zusammenhaengende aktivierte Buttons)
     */
    public boolean wincheck(){
        for (int i = 0; i < buttons.length; i++) {
            int counter = 0;
            for (int j = 0; j < buttons.length; j++) {
                if (text.contains(this.buttons[i][j].getText()) && this.buttons[i][j].getBackground() == Color.red) {
                    counter++;
                }
            }
            if (counter == 5) {
                return true;
            }
        }

        for (int j = 0; j < buttons.length; j++) {
            int counter = 0;
            for (int i = 0; i < buttons.length; i++) {
                if (text.contains(this.buttons[i][j].getText()) && this.buttons[i][j].getBackground() == Color.red) {
                    counter++;
                }
            }
            if (counter == 5) {
                return true;
            }
        }

        int counter = 0;
        for(int j=0;j <buttons.length; j++) {
            if (text.contains(this.buttons[j][j].getText()) && this.buttons[j][j].getBackground() == Color.red) {
                counter++;
            }
            if(counter == 5)
                return true;
        }


        counter = 0;
        for(int j=0;j <buttons.length; j++) {
            if (text.contains(this.buttons[buttons.length-1-j][j].getText()) && this.buttons[buttons.length-1-j][j].getBackground() == Color.red) {
                counter++;
            }
            if(counter == 5)
                return true;
        }
        
        return false;
    }

    /*
     *liest ein, welche Rolle gewaehlt wird
     */
    public void setRole() {
        role = "Server";
        out.println(role);
        out.flush();
        String info = "";
        try {
            info = networkIn.readLine();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }
        if (info.equals("Server")) {
            role = "Server";
        } else {
            role = "Client";
        }
    }

    
/*
 * liest Spielfeld vom Server ein
 */
    public String[][] getFields() {

        //client/server
        String field = "";
        try {
            field = networkIn.readLine();
        } catch (IOException e) {
        }
        String[] gamefield = field.split(" ", 0);

        int fieldSize = (int) java.lang.Math.sqrt(gamefield.length);
        String[][] arrayField = new String[fieldSize][fieldSize];

        //spielfeld mit 25 Wörtern aus der Textdatei
        int counter = 0;
        for (int i = 0; i < fieldSize; i++) {
            for (int j = 0; j < fieldSize; j++) {
                arrayField[i][j] = gamefield[counter++];
            }
        }

        return arrayField;
    }

    /*
     * liest verwendete Textdatei ein, falls das hier der Spieler hier das Spiel
     * startet und sendet sie an den Server
     */
    public void sendFile() {
        String path = jTextField3.getText();
        if (role.equals("Server")) {
            try {
                BufferedReader br = new BufferedReader(new FileReader(path));
                String empty = "";
                String line;

                while ((line = br.readLine()) != null) {
                    empty = empty + line;
                }

                br.close();

                out.println(empty);
                out.flush();

            } catch (IOException e) {

                e.printStackTrace();
            }
        }
    }

    /*
     * sendet Spielernamen an Server, gibt zurueck, ob der Name vom Server akzeptiert
     * wurde oder nicht
     */
    public boolean sendName() {
        String name = jTextField2.getText();
        try {
            out = new PrintWriter(a.getOutputStream());
            System.out.println("Connected to echo server");
            networkIn = new BufferedReader(
                    new InputStreamReader(a.getInputStream()));
            //BufferedReader userIn = new BufferedReader(new InputStreamReader(
            //		System.in));

            out.println(name);
            out.flush();

            String in = networkIn.readLine();

            if (in.equals("yes")) {
                return true;
            }
            if (in.equals("no")) {
                return false;
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            //e.printStackTrace();
            return false;
        }
        return false;
    }

    @Action
    public void quit() {
        System.exit(0);
    }

    @Action
    public void start() {
        ClientThread a = new ClientThread(out, networkIn, jLabel1, jList1,text,win);
        a.start();
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JList jList1;
    private javax.swing.JList jList2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JTextField jTextField3;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    // End of variables declaration//GEN-END:variables
    private javax.swing.JButton[][] buttons;
    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;
    private Socket a = null;
    public LinkedList <String> text  = new LinkedList<String>();
    public PrintWriter out = null;
    public BufferedReader networkIn = null;
    String role;
    public boolean win;
    private JDialog aboutBox;
}

/*
 * Spielfunktionalität, "main"
 */
class ClientThread extends Thread {
    public PrintWriter out = null;
    public BufferedReader networkIn = null;
    public javax.swing.JLabel jLabel1 = null;
    public javax.swing.JList jList1;
    public javax.swing.DefaultListModel einfuege;
    public LinkedList<String> text;
    public boolean win = false;
    public ClientThread (PrintWriter a,BufferedReader b,javax.swing.JLabel c,javax.swing.JList d,LinkedList e, boolean f )
    {
        this.out=a;
        this.networkIn=b;
        this.jLabel1=c;
        this.jList1=d;
        this.text=e;
        this.win=f;
        einfuege = new javax.swing.DefaultListModel();
    }
    public void run() {
        //Dauerschleife für den Empfang von Informationen vom Server
        try {

            String lastWord ="";
            String lastlastWord ="";

            while (true) {
                String[] data = new String[2];
                data[0] = "";
                data[1] = "";
                String inputData = networkIn.readLine();

                if (inputData == null) {
                    break;
                }

                data = inputData.split(" ", 0);
                String command = "", value = "";

                command = data[0];
                if (data[1] != null) {
                    value = data[1];
                }

                // "quit" beendet die Verbindung
                if (command.equals("quit")) {
                    break;
                }

                // "user" gibt alle User zurück
                String[] user;
                
                if (command.equals("user")) {
                    user = value.split(",");
                    this.einfuege.clear();
                    for (int i = 0; i < user.length; i++) {
                        //System.out.println(user[i]);
                        
                        this.einfuege.addElement(user[i]);
                        this.jList1.setModel(einfuege);
                    }
                }
                // "win" beendet das Spiel mit Ausgabe des Gewinners
                if (command.equals("win")) {
                    if(!jLabel1.getText().equals("BINGO!")){
                        jLabel1.setText("" + value + " hat gewonnen!");
                    }
                    out.println("quit");
                    out.flush();
                    break;
                }

                // "word" gibt das nächste Wort der Liste zurück
                if (command.equals("word")) {
                    //System.out.println("Server sagt: " + value);
                    win = false;
                    if(jLabel1.getText().equals("BINGO!")){
                        win = true;
                    }else{
                        jLabel1.setText("..."+lastlastWord+" "+lastWord+" "+value+"...");
                        lastlastWord = lastWord;
                        lastWord = value;
                        text.add(value);
                    }
                    out.println("ping");
                    out.flush();
                    //noch einzufügen als globale variabel win
                    if (win) {
                        out.println("win");
                        out.flush();
                    } else {
                        out.println("nowin");
                        out.flush();
                    }
                    out.println("ping");
                    out.flush();
                }

            }

            out.close();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }
    }
}
